package gokv

import (
	"bytes"
	"gitee.com/Cauchy_AQ/gokv/index"
)

// Iterator 迭代器
// 用户层级使用
type Iterator struct {
	db       *DB
	iterator index.Iterator
	opt      *IteratorOptions
}

// NewIterator 初始化迭代器
func (d *DB) NewIterator(option *IteratorOptions) *Iterator {
	indexIterator := d.index.Iterator(option.Reverse)
	return &Iterator{
		db:       d,
		iterator: indexIterator,
		opt:      option,
	}
}

// Rewind 重新返回迭代起点
func (i *Iterator) Rewind() {
	i.iterator.Rewind()
	i.skipToNext()
}

// Seek 根据传入 key 找到第一个大于（或小于）等于的目标 key，根据这个 key 开始遍历
func (i *Iterator) Seek(key []byte) {
	i.iterator.Seek(key)
	i.skipToNext()
}

// Next 跳转到下一个 key
func (i *Iterator) Next() {
	i.iterator.Next()
	i.skipToNext()
}

// Valid 是否有效，判断是否遍历完了 key
func (i *Iterator) Valid() bool {
	return i.iterator.Valid()
}

// Key 获取迭代器当前位置的 key
func (i *Iterator) Key() []byte {
	return i.iterator.Key()
}

// Value 获取当前迭代位置的索引位置信息
func (i *Iterator) Value() ([]byte, error) {
	// 获取索引信息
	logRecordPos := i.iterator.Value()

	// 读取数据前持有锁
	i.db.mtx.RLock()
	defer i.db.mtx.RUnlock()

	// 获取实际value值
	return i.db.getValueByPosition(logRecordPos)
}

// Close 关闭迭代器
func (i *Iterator) Close() {
	i.iterator.Close()
}

// skipToNext 过滤 prefix 不匹配的数据
// TODO: 优化: 根据 prefix Seek，不应该Next一步步走
func (i *Iterator) skipToNext() {
	prefixLen := len(i.opt.Prefix)
	if prefixLen == 0 {
		return
	}
	for ; i.iterator.Valid(); i.iterator.Next() {
		key := i.iterator.Key()
		if prefixLen <= len(key) && bytes.Compare(i.opt.Prefix, key[:prefixLen]) == 0 {
			break
		}
	}
}
